home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
pmode
/
pmode30b
/
pm24sh.asm
< prev
next >
Wrap
Assembly Source File
|
1994-05-29
|
37KB
|
1,082 lines
; PMODE v2.4 shell for PMODE v3.0
; By Tran (a.k.a. Thomas Pytel).
.386p
LOWMIN = 0 ; minimum free low memory (in K)
EXTMIN = 0 ; minimum free extended memory (in K)
SELECTORS = 8 ; extra selectors for allocation
STAKMAIN = 100h ; main execution stream stack size (in para)
STAKRMODE = 10h ; real mode call stack size (in para)
STAKPMODE = 20h ; protected mode call stack size (in para)
MODENESTING = 8 ; max number of nested mode switches
RMODENUM = (MODENESTING+1) shr 1
PMODENUM = MODENESTING shr 1
STAKSIZE = STAKMAIN+(PMODENUM*STAKPMODE)+(RMODENUM*STAKRMODE)
.errnz STAKSIZE gt 0fffh ; error if stack greater than 64k
PMODE_TEXT segment para public use16 'CODE'
PMODE_TEXT ends
code16 segment para public use16
code16 ends
code32 segment para public use32
code32 ends
codeend segment para stack use32 'stack'
codeend ends
extrn _pm_info:far, _pm_init:far
extrn _pm_pagetables:byte, _pm_selectors:word, _pm_rmstacklen:word
extrn _pm_pmstacklen:word, _pm_rmstacks:byte, _pm_pmstacks:byte
extrn _pm_callbacks:byte
;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
; Real mode and 16bit code
;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
code16 segment para public use16
assume cs:code16, ds:code16
org 0
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
; 16 bit common system data
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
exiterrmsgtbl dw errmsg0,errmsg2,d_errmsg0,errmsg4,d_errmsg3,d_errmsg1
errmsg0 db '386 or better not detected!!!',7,'$'
errmsg1 db 'Not enough low memory!!!',7,'$'
errmsg2 db 'System is already in V86 mode, and no VCPI or DPMI found!!!',7,'$'
errmsg3 db 'Not enough extended memory!!!',7,'$'
errmsg4 db 'Couldn''t enable A20 gate!!!',7,'$'
errmsg5 db 'Extended memory allocation failure. (weird eh???)',7,'$'
nullint db 0cfh ; IRET instruction
exitrout dw exit ; exit routine, modified if XMS, VCPI
pmbuflen dw ? ; length of PMODE low buffer
savedstakoff dw ? ; current saved stack offset
savedstakseg dw ? ; current saved stack segment
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
; 16 bit common system code
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
;═════════════════════════════════════════════════════════════════════════════
intreal: ; real mode int, load FS and GS here
pushf
;-----------------------------------------------------------------------------
callreal: ; real mode call, load FS and GS here
push cs
push offset icreald
mov fs,cs:v86r_fs
mov gs,cs:v86r_gs
mov eax,cs:v86r_eax
mov ecx,cs:v86r_ecx
mov edx,cs:v86r_edx
mov ebx,cs:v86r_ebx
mov esi,cs:v86r_esi
mov edi,cs:v86r_edi
mov ebp,cs:v86r_ebp
;-----------------------------------------------------------------------------
icreal: ; real mode int, call, or IRQ
db 66h,68h ; PUSH destination addx
icrealm1 dd ? ;
icrealm0 db ? ; CLI or STI
retf
;-----------------------------------------------------------------------------
icreald: ; done with real int or call
cli
pushf
pop cs:v86r_flags
mov cs:v86r_eax,eax
mov cs:v86r_ecx,ecx
mov cs:v86r_edx,edx
mov cs:v86r_ebx,ebx
mov cs:v86r_esi,esi
mov cs:v86r_edi,edi
mov cs:v86r_ebp,ebp
mov cs:v86r_ds,ds
mov cs:v86r_es,es
mov cs:v86r_fs,fs
mov cs:v86r_gs,gs
icreald2:
mov ax,cs
mov ds,ax
icrealm2 label word ; return to pmode modifiable to JMP
;-----------------------------------------------------------------------------
mov ebx,ds:dp_savedstakoff ; DPMI return to pmode
mov dx,ds:dp_savedstaksel
mov edi,offset dp_int3_d
mov si,ds:_selcode
mov cx,dx
mov ax,ds:_seldata
jmp ds:d_switchaddx
;═════════════════════════════════════════════════════════════════════════════
int32: ; real mode INT32: EDX=off
pushad
push ds es fs gs
cli
mov ax,cs
mov ds,ax
mov ds:p_cpmodem0,edx
mov al,[esp+45]
shr al,1
and al,1
add al,0fah
mov ds:p_cpmodem1,al
push savedstakoff
push savedstakseg
movzx ebx,ds:nextmodestack
lea eax,[ebx-STAKPMODE*16]
mov ds:nextmodestack,ax
add ebx,ds:realstackbase
mov savedstakseg,ss
int32m0 label word ; jump to pmode, modifiable
;-----------------------------------------------------------------------------
sub sp,ds:dp_savelen
mov savedstakoff,sp
mov ax,ss ; DPMI jump to pmode
mov es,ax
mov di,sp
xor al,al
call d_saveaddx
mov ax,ds:_seldata
mov cx,ax
mov dx,ax
mov edi,offset p_cpmode0
mov si,ds:_selcode
jmp ds:d_switchaddx
;═════════════════════════════════════════════════════════════════════════════
int32d0: ; DPMI done with pmode call
mov di,sp
mov al,1
call d_saveaddx
add sp,ds:dp_savelen
;-----------------------------------------------------------------------------
int32d2: ; done from all
pop savedstakseg
pop savedstakoff
add ds:nextmodestack,STAKPMODE*16
mov bx,ds:v86r_flags
mov ax,[esp+44]
and ax,not 8d5h
and bx,8d5h
or ax,bx
mov [esp+44],ax
pop gs fs es ds
popad
iret
;─────────────────────────────────────────────────────────────────────────────
pregetlomem: ; Get low memory or abort
add eax,ds:_lomembase
mov ebx,ds:_lomemtop
cmp eax,ebx
ja short pregetlomema
mov ecx,eax
xchg eax,ds:_lomembase
sub ebx,ecx
cmp ebx,LOWMIN*1024
jb short pregetlomema
ret
pregetlomema:
mov dx,offset errmsg1
;─────────────────────────────────────────────────────────────────────────────
exit16err: ; Exit program with message
mov ah,9
int 21h
jmp exitrout
;-----------------------------------------------------------------------------
exit: ; Guess what???
mov ah,4ch
mov al,ds:_exitcode
int 21h
;═════════════════════════════════════════════════════════════════════════════
start16: ; Program begins here
cli
cld
push cs
pop ds
push es ; set up PMODE variables
mov ax,PMODE_TEXT
mov es,ax
mov es:_pm_pagetables,(EXTMIN/4096)+1
mov es:_pm_selectors,3+SELECTORS
mov es:_pm_rmstacklen,STAKRMODE
mov es:_pm_rmstacks,MODENESTING/2
xor eax,eax
mov es:_pm_pmstacklen,ax
mov es:_pm_pmstacks,al
mov es:_pm_callbacks,al
pop es
call _pm_info ; get protected mode info
mov si,ax
mov dx,exiterrmsgtbl[si]
jc exit16err ; if error, exit with error message
mov pmbuflen,bx
or ds:_sysbyte0,ch ; set system type byte
mov ax,es ; set up a bunch of pointers
movzx eax,ax
shl eax,4
mov ds:_pspa,eax
mov eax,code16
shl eax,4
mov ds:_code16a,eax
or dword ptr ds:gdt32code16[2],eax
or dword ptr ds:gdt32data16[2],eax
mov ebx,code32
shl ebx,4
mov ds:_code32a,ebx
or dword ptr ds:gdt32code32[2],ebx
or dword ptr ds:gdt32data32[2],ebx
mov eax,codeend
shl eax,4
sub eax,ebx
mov ds:_lomembase,eax
mov ds:realstackbase,eax
movzx eax,word ptr es:[2]
shl eax,4
sub eax,ebx
mov ds:_lomemtop,eax
mov eax,STAKSIZE*16 ; get stack memory
call pregetlomem
push es ; save PSP seg (DPMI chek kills ES)
pop fs
jmp d_start
;─────────────────────────────────────────────────────────────────────────────
; BL=low PIC val, BH=high PIC val
setintslots: ; set int nums in table to PIC vals
mov edi,offset ds:intslottbl
mov cl,8
setintslotsl0:
mov [di],bl
inc di
inc bl
dec cl
jnz setintslotsl0
mov cl,8
setintslotsl1:
mov [di],bh
inc di
inc bh
dec cl
jnz setintslotsl1
ret
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
; 16 bit DPMI system data
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
d_errmsg0 db 'DPMI host is not 32bit!!!',7,'$'
d_errmsg1 db 'Ran out of DPMI descriptors!!!',7,'$'
d_errmsg2 db 'Couldn''t set DPMI descriptors as needed!!!',7,'$'
d_errmsg3 db 'Couldn''t enter 32bit protected mode!!!',7,'$'
d_memhandlep db 0 ; 1=memory handle present, 0=not
d_enterpmode dw ?,? ; DPMI switch to pmode addx
d_pspsel dw ? ; stupid PSP selector
d_oldenvsegsel dw ? ; stupid selector we dont want
d_memhandle dw ?,? ; DPMI memory block handle
d_switchaddx dd ? ; switch to pmode addx
d_saveaddx dd ? ; save/restore state addx
d_nintoff dd offset dp_irq0,offset dp_irq1,offset dp_irq2,offset dp_irq3
dd offset dp_irq4,offset dp_irq5,offset dp_irq6,offset dp_irq7
dd offset dp_irq8,offset dp_irq9,offset dp_irqa,offset dp_irqb
dd offset dp_irqc,offset dp_irqd,offset dp_irqe,offset dp_irqf
dd offset dp_int33,offset dp_int32,offset dp_int33,offset dp_int32
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
; 16 bit DPMI system code
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
;═════════════════════════════════════════════════════════════════════════════
d_retreal: ; Return to real mode
cmp d_memhandlep,0 ; free memory block if present
je short d_retrealf0
mov di,d_memhandle[0]
mov si,d_memhandle[2]
mov ax,502h
int 31h
d_retrealf0:
mov ax,205h ; restore all int vektorz needed
mov edi,19
d_retreall0:
mov bl,ds:intslottbl[edi]
lea ebp,[edi*2+edi]
mov edx,dword ptr ds:dp_ointbuf[ebp*2]
mov cx,word ptr ds:dp_ointbuf[ebp*2+4]
int 31h
sub di,1
jnc d_retreall0
jmp short d_exit
;─────────────────────────────────────────────────────────────────────────────
d_exit16err: ; DPMI Exit with error message
mov ds:v86r_ds,code16
mov ds:v86r_ah,9
mov ax,300h
mov bx,21h
xor cx,cx
mov edi,offset ds:v86r_edi
push ds
pop es
int 31h
;─────────────────────────────────────────────────────────────────────────────
d_exit: ; DPMI exit to real mode
mov es,d_pspsel ; restore env selector
mov ax,d_oldenvsegsel
mov es:[2ch],ax
jmp exit
;═════════════════════════════════════════════════════════════════════════════
d_start: ; Start in a crappy DPMI system
movzx eax,pmbuflen ; get mem for DPMI low memory block
shl eax,4
call pregetlomem
shr eax,4
add ax,code32
mov es,ax
call _pm_init ; switch to protected mode
cli ; I don't trust myself
mov dx,offset d_errmsg3
jc exit16err
mov ds:v86r_dx,offset d_errmsg1 ; prepare for abort maybe
pop ax ; swap old env seg with selector
xchg ax,es:[2ch]
mov d_oldenvsegsel,ax
mov d_pspsel,es ; store stupid selectors
mov ds:data16sel,ds
mov ds:code16sel,cs
push ds ; no more need for PSP
pop es
mov ax,3 ; get selector increment value
int 31h
mov bx,ax
xor ax,ax ; get needed selectors
mov cx,3+SELECTORS
int 31h
jc d_exit16err
mov si,ax ; set up descriptors
mov ds:_selcode,ax
lea ecx,[eax+ebx]
mov ds:_seldata,cx
lea ebp,[ecx+ebx]
mov ds:_selzero,bp
lea eax,[ebp+ebx]
if SELECTORS ne 0
mov ds:selectorbase,ax
mov ds:selectorinc,bx
endif
mov ds:v86r_dx,offset d_errmsg2
mov ax,cs ; set DPL fields of descriptors
lar ax,ax
and ah,60h
or byte ptr ds:gdt32code32[5],ah
or byte ptr ds:gdt32data32[5],ah
or byte ptr ds:gdt32zero32[5],ah
mov ax,0ch ; set descriptors from GDT
mov bx,si
mov edi,offset ds:gdt32code32
int 31h
jc d_exit16err
mov bx,cx
mov edi,offset ds:gdt32data32
int 31h
jc d_exit16err
mov bx,bp
mov edi,offset ds:gdt32zero32
int 31h
jc d_exit16err
if SELECTORS ne 0
mov bx,ds:selectorbase ; set up extra allocatable selectors
mov dx,SELECTORS
d_startl1:
int 31h
jc d_exit16err
add bx,ds:selectorinc
dec dx
jnz d_startl1
endif
mov es,cx ; ES, FS, and GS what they should be
mov fs,cx
mov gs,bp
mov edi,ds:_lomembase ; chek and get extended memory
mov eax,ds:_lomemtop
sub eax,edi
cmp eax,48
mov ds:v86r_dx,offset errmsg1
jb d_exit16err
mov ax,500h
int 31h
mov eax,es:[edi]
lea edx,[eax+1024]
mov ds:v86r_dx,offset errmsg3
d_startl2:
sub edx,1024
jnc short d_startf2
xor edx,edx
d_startf2:
cmp edx,EXTMIN*1024
jb d_exit16err
or edx,edx
jz short d_startf1
mov cx,dx
shld ebx,edx,16
mov ax,501h
int 31h
jc d_startl2
mov ds:d_memhandle[0],di
mov ds:d_memhandle[2],si
mov ds:d_memhandlep,1
shl ebx,16
mov bx,cx
sub ebx,ds:_code32a
mov ds:_himembase,ebx
add ebx,edx
mov ds:_himemtop,ebx
d_startf1:
mov ax,305h ; get save/restore state addxs
int 31h
mov ds:dp_savelen,ax
mov dword ptr ds:dp_saveaddx[0],edi
mov word ptr ds:dp_saveaddx[4],si
mov word ptr d_saveaddx[0],cx
mov word ptr d_saveaddx[2],bx
mov ax,306h ; get switch mode addxs
int 31h
mov dword ptr ds:dp_switchaddx[0],edi
mov word ptr ds:dp_switchaddx[4],si
mov word ptr d_switchaddx[0],cx
mov word ptr d_switchaddx[2],bx
mov ax,400h ; set IRQ handlers to PIC values
int 31h
xchg dl,dh
mov bx,dx
call setintslots
mov ah,2 ; backup and set all int vektorz
mov si,ds:_selcode
mov edi,19
d_startl0:
mov bl,ds:intslottbl[edi]
mov al,4
int 31h
lea ebp,[edi*2+edi]
mov dword ptr ds:dp_ointbuf[ebp*2],edx
mov word ptr ds:dp_ointbuf[ebp*2+4],cx
mov al,5
mov edx,d_nintoff[edi*4]
mov cx,si
int 31h
sub di,1
jnc d_startl0
mov ax,es ; set up needed regs & go on to 32bit
mov ss,ax
add esp,ds:realstackbase
mov ds,ax
push dword ptr cs:_selcode
push offset p_start
db 66h,0cbh ; 32bit RETF
code16 ends
;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
; 32bit pmode code
;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
code32 segment para public use32
assume cs:code32, ds:code32
org 0
extrn _main:near
public _exit, _ret, _getmem, _getlomem, _gethimem, _lomemsize, _himemsize
public _getirqmask, _setirqmask, _getselector, _freeselector, _rmpmirqset
public _rmpmirqfree
public v86r_eax, v86r_ebx, v86r_ecx, v86r_edx, v86r_esi, v86r_edi, v86r_ebp
public v86r_ax, v86r_bx, v86r_cx, v86r_dx, v86r_si, v86r_di, v86r_bp
public v86r_al, v86r_ah, v86r_bl, v86r_bh, v86r_cl, v86r_ch, v86r_dl, v86r_dh
public v86r_ds, v86r_es, v86r_fs, v86r_gs
public _selcode, _seldata, _selzero, _lomembase, _lomemtop, _himembase
public _himemtop, _pspa, _code16a, _code32a, _getirqvect, _setirqvect
public _sysbyte0, _irqmode, _setselector, _exitcode
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
; 32 bit common system data
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
_lomembase dd ? ; low mem base for allocation
_lomemtop dd ? ; top of low mem
_himembase dd 0 ; high mem base for allocation
_himemtop dd 0 ; top of high mem
_pspa dd ? ; offset of start of PSP from 0
_code16a dd ? ; offset of start of 16bit code from 0
_code32a dd ? ; offset of start of 32bit code from 0
_selcode dw 8 ; code segment selector
_seldata dw 10h ; data segment alias for code
_selzero dw 18h ; data segment starting at 0:0
_irqmode dw 0ffffh ; IRQ mode bits: 0=normal, 1=safe
db 0ffh ; misc byte, has to follow _irqmode
_sysbyte0 db 0 ; system bits:
; 0-1: 0=raw, 1=XMS, 2=VCPI, 3=DPMI
_exitcode db 0 ; exit code for int21h ah=4ch
align 4
_getirqvect dd dp_getirqvect ; get IRQ handler offset routine addx
_setirqvect dd dp_setirqvect ; set IRQ handler offset routine addx
_setselector dd dp_setselector ; set a selector addx offset addx
gdt32 dq 0
gdt32code32 db 0ffh,0ffh,0,0,0,9ah,0cfh,0
gdt32data32 db 0ffh,0ffh,0,0,0,92h,0cfh,0
gdt32zero32 db 0ffh,0ffh,0,0,0,92h,0cfh,0
gdt32code16 db 0ffh,0ffh,0,0,0,9ah,0,0
gdt32data16 db 0ffh,0ffh,0,0,0,92h,0,0
gdt32task db 0ffh,0ffh,0,0,0,89h,0,0
gdt32vcpi dq 3 dup(?)
if SELECTORS ne 0
gdt32free db SELECTORS dup(0ffh,0ffh,0,0,0,92h,0cfh,0)
endif
v86r_edi label dword ; vregs for pmode<>real communication
v86r_di dw ?, ? ; needz to stay this way cuz its a
v86r_esi label dword ; stupid DPMI structure thingy
v86r_si dw ?, ?
v86r_ebp label dword
v86r_bp dw ?, ?
dd 0
v86r_ebx label dword
v86r_bx label word
v86r_bl db ?
v86r_bh db ?, ?,?
v86r_edx label dword
v86r_dx label word
v86r_dl db ?
v86r_dh db ?, ?,?
v86r_ecx label dword
v86r_cx label word
v86r_cl db ?
v86r_ch db ?, ?,?
v86r_eax label dword
v86r_ax label word
v86r_al db ?
v86r_ah db ?, ?,?
v86r_flags dw ?
v86r_es dw ?
v86r_ds dw ?
v86r_fs dw ?
v86r_gs dw ?
dd 0,0
oint1bvect dd ? ; old real int 1bh vektor (ctrl+break)
oint32vect dd ? ; old real int 32h vector
oirqmask dw ? ; old port 21h and 0a1h masks
intslottbl db 8,9,0ah,0bh,0ch,0dh,0eh,0fh,70h,71h,72h,73h,74h,75h,76h,77h
db 35h,34h,33h,32h,31h,0,1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh
if SELECTORS ne 0
selectorbase dw 50h
selectorinc dw 8
selectorfree db SELECTORS dup(0)
endif
code16off dw d_retreal ; offset in 16bit of exit function
code16sel dw 20h ; 16bit pmode code selector
data16sel dw 28h ; 16bit pmode data selector
nextmodestack dw (STAKSIZE-STAKMAIN)*16 ; stack for next mode switch
realstackbase dd ? ; linear ptr to beginning of codeend
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
; 32 bit common system code
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
;═════════════════════════════════════════════════════════════════════════════
p_cpmode0: ; call pmode, load FS and GS
mov fs,_seldata
mov gs,_selzero
;-----------------------------------------------------------------------------
p_cpmode: ; call pmode routine from real
push offset p_cpmoded
cld
mov eax,v86r_eax
mov ecx,v86r_ecx
mov edx,v86r_edx
mov ebx,v86r_ebx
mov esi,v86r_esi
mov edi,v86r_edi
mov ebp,v86r_ebp
db 68h ; PUSH destination address
p_cpmodem0 dd ? ;
p_cpmodem1 db ? ; CLI or STI
ret
;-----------------------------------------------------------------------------
p_cpmoded: ; call to pmode done
cli
pushf
pop v86r_flags
mov v86r_eax,eax
mov v86r_ecx,ecx
mov v86r_edx,edx
mov v86r_ebx,ebx
mov v86r_esi,esi
mov v86r_edi,edi
mov v86r_ebp,ebp
mov ecx,_code16a
p_cpmodem2 label word ; return to real, modifiable to JMP
;-----------------------------------------------------------------------------
movzx ebx,gs:savedstakoff[ecx] ; DPMI return to real mode
mov dx,gs:savedstakseg[ecx]
mov ax,code16
mov cx,dx
mov si,ax
mov edi,offset int32d0
jmp dp_switchaddx
;═════════════════════════════════════════════════════════════════════════════
p_start: ; common 32bit start
mov eax,gs:[1bh*4] ; neutralize crtl+break
mov oint1bvect,eax
db 65h,67h,0c7h,6 ; MOV DWORD PTR GS:[1bh*4],code16:nullint
dw 1bh*4,nullint,code16 ;
mov eax,gs:[32h*4] ; set up for new real mode INT32
mov oint32vect,eax
db 65h,67h,0c7h,6 ; MOV DWORD PTR GS:[32h*4],code16:int32
dw 32h*4,int32,code16 ;
in al,21h ; save old PIC masks
mov ah,al
in al,0a1h
mov oirqmask,ax
jmp _main ; go to main code
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; Allocate any mem, (first cheks low, then high)
; In:
; EAX - size requested
; Out:
; CF=0 - memory allocated
; CF=1 - not enough mem
; EAX - linear pointer to mem or ?
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
_getmem:
push eax
call _getlomem
jnc short getmemd
pop eax
jmp short _gethimem
getmemd:
add esp,4
_ret: ; generic RET instruction
ret
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; Allocate some low mem
; In:
; EAX - size requested
; Out:
; CF=0 - memory allocated
; CF=1 - not enough mem
; EAX - linear pointer to mem or ?
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
_getlomem:
add eax,_lomembase
cmp eax,_lomemtop
ja short getmemerr
xchg eax,_lomembase
clc
ret
getmemerr:
stc
ret
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; Allocate some high mem
; In:
; EAX - size requested
; Out:
; CF=0 - memory allocated
; CF=1 - not enough mem
; EAX - linear pointer to mem or ?
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
_gethimem:
add eax,_himembase
cmp eax,_himemtop
ja short getmemerr
xchg eax,_himembase
clc
ret
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; Get amount of free low mem
; Out:
; EAX - number of bytes free
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
_lomemsize:
mov eax,_lomemtop
sub eax,_lomembase
ret
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; Get amount of free high mem
; Out:
; EAX - number of bytes free
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
_himemsize:
mov eax,_himemtop
sub eax,_himembase
ret
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; Get status of IRQ mask bit
; In:
; BL - IRQ num (0-15)
; Out:
; AL - status: 0=enabled, 1=disabled
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
_getirqmask:
push ax
in al,0a1h
mov ah,al
in al,21h
xchg cl,bl
shr ax,cl
xchg cl,bl
and al,1
mov [esp],al
pop ax
ret
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; Set status of IRQ mask bit
; In:
; BL - IRQ num (0-15)
; AL - status: 0=enabled, 1=disabled
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
_setirqmask:
push ax bx cx dx
mov cl,bl
mov bx,0fffeh
movzx dx,al
rol bx,cl
shl dx,cl
in al,0a1h
mov ah,al
in al,21h
and ax,bx
or ax,dx
out 21h,al
mov al,ah
out 0a1h,al
pop dx cx bx ax
ret
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; Set a real mode IRQ vect to redirect to pmode
; In:
; BL - IRQ number
; EDX - offset of IRQ handler
; EDI -> 21 byte buffer for code stub created
; Out:
; EAX - old seg:off of real mode IRQ handler
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
rmpmirqsetd0:
db 66h,52h ; PUSH EDX
db 66h,0bah,?,?,?,? ; MOV EDX,?
db 0cdh,32h ; INT 32h
db 66h,5ah ; POP EDX
db 0cfh ; IRET
db 9ch ; PUSHFD
db 0eh ; PUSH CS
db 0e8h,?,?,?,? ; CALL ?
db 0c3h ; RET
;-----------------------------------------------------------------------------
_rmpmirqset:
push esi edi
mov esi,offset rmpmirqsetd0
lea eax,[edi+13]
mov [esi+4],eax
add eax,7
sub eax,edx
neg eax
mov [esi+16],eax
mov eax,edi
movsd
movsd
movsd
movsd
movsd
movsb
add eax,_code32a
shl eax,12
shr ax,12
movzx edi,bl
cmp edi,8
jb short rmpmirqsetf0
add edi,60h
rmpmirqsetf0:
xchg eax,gs:[edi*4+20h]
pop edi esi
ret
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; Reset a real more IRQ vect back to normal (just sets real mode IRQ vect)
; In:
; BL - IRQ number
; EAX - seg:off of real mode IRQ handler
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
_rmpmirqfree:
push ebx
movzx ebx,bl
cmp bl,8
jb short rmpmirqfreef0
add bl,60h
rmpmirqfreef0:
mov gs:[ebx*4+20h],eax
pop ebx
ret
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; Allocate a selector
; Out:
; CF=1 - selector not allocated
; CF=0 - selector allocated
; AX - 4G data selector or ?
; Notes:
; The selector returned is for a 4G r/w data segment with an undefined base
; address.
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
_getselector:
if SELECTORS eq 0
stc
ret
else
push ecx edi
mov edi,offset selectorfree
mov ecx,SELECTORS
mov al,0
repne scasb
jne short getselectorf0
mov byte ptr [edi-1],1
sub ecx,SELECTORS-1
neg ecx
imul cx,selectorinc
mov ax,selectorbase
add ax,cx
clc
jmp short getselectorf1
getselectorf0:
stc
getselectorf1:
pop edi ecx
ret
endif
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; Free an allocated selector
; In:
; AX - selector
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
_freeselector:
if SELECTORS ne 0
push eax dx
sub ax,selectorbase
xor dx,dx
div selectorinc
movzx eax,ax
mov selectorfree[eax],0
pop dx eax
endif
ret
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; Exit to real mode
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
_exit:
cli
mov eax,oint1bvect ; restore ctrl+break
mov gs:[1bh*4],eax
mov eax,oint32vect ; restore real mode int 32h vector
mov gs:[32h*4],eax
mov ax,oirqmask ; restore PIC masks
out 0a1h,al
mov al,ah
out 21h,al
push code16sel ; go to 16bit pmode exit code
push code16off
mov ds,data16sel
db 66h,0cbh ; 16bit RETF
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
; 32 bit DPMI system data
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
dp_switchaddx df ? ; switch to real mode addx
dp_saveaddx df ? ; save/restore state addx
dp_savelen dw 0,0 ; length of state buffer
dp_savedstakoff dd ? ; current saved stack offset
dp_savedstaksel dw ? ; current saved stack selector
dp_ointbuf df 20 dup(?) ; saved interrupt addx buffer
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
; 32 bit DPMI system code
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
;═════════════════════════════════════════════════════════════════════════════
dp_int32: ; DPMI INT32/34: CX:DX=seg:off
pushad
shl ecx,16
mov cx,dx
mov bp,offset callreal
mov dl,1
jmp short dp_int3_
;═════════════════════════════════════════════════════════════════════════════
dp_int33: ; DPMI INT33/35: AL=int num
pushad
movzx eax,al
mov ecx,gs:[eax*4]
mov bp,offset intreal
xor dl,dl
;-----------------------------------------------------------------------------
dp_int3_: ; DPMI int or call to real mode
mov ax,900h
int 31h
push ax
and al,dl
add al,0fah
mov ebx,_code16a
mov gs:icrealm0[ebx],al
mov gs:icrealm1[ebx],ecx
push dp_savedstakoff
push dp_savedstaksel
movzx ebx,nextmodestack
lea eax,[ebx-STAKRMODE*16]
mov nextmodestack,ax
mov ax,ss
mov es,ax
sub esp,dword ptr dp_savelen
mov edi,esp
xor al,al
call dp_saveaddx
mov dp_savedstakoff,esp
mov dp_savedstaksel,ss
mov dx,codeend
mov ax,v86r_ds
mov cx,v86r_es
movzx edi,bp
mov si,code16
jmp dp_switchaddx
;-----------------------------------------------------------------------------
dp_int3_d: ; done with real mode int or call
mov edi,esp
mov al,1
call dp_saveaddx
add esp,dword ptr dp_savelen
pop dp_savedstaksel
pop dp_savedstakoff
add nextmodestack,STAKRMODE*16
mov bx,v86r_flags
pop ax
int 31h
mov ax,ds
mov es,ax
mov fs,ax
mov gs,_selzero
mov ax,[esp+40]
and ax,not 8d5h
and bx,8d5h
or ax,bx
mov [esp+40],ax
popad
iretd
;═════════════════════════════════════════════════════════════════════════════
; DPMI IRQ redirectors (needed to make all IRQ vector selectors = CS)
dp_irq0:
jmp cs:dp_ointbuf[0]
dp_irq1:
jmp cs:dp_ointbuf[6]
dp_irq2:
jmp cs:dp_ointbuf[12]
dp_irq3:
jmp cs:dp_ointbuf[18]
dp_irq4:
jmp cs:dp_ointbuf[24]
dp_irq5:
jmp cs:dp_ointbuf[30]
dp_irq6:
jmp cs:dp_ointbuf[36]
dp_irq7:
jmp cs:dp_ointbuf[42]
dp_irq8:
jmp cs:dp_ointbuf[48]
dp_irq9:
jmp cs:dp_ointbuf[54]
dp_irqa:
jmp cs:dp_ointbuf[60]
dp_irqb:
jmp cs:dp_ointbuf[66]
dp_irqc:
jmp cs:dp_ointbuf[72]
dp_irqd:
jmp cs:dp_ointbuf[78]
dp_irqe:
jmp cs:dp_ointbuf[84]
dp_irqf:
jmp cs:dp_ointbuf[90]
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; DPMI get IRQ handler offset
; In:
; BL - IRQ num (0-0fh)
; Out:
; EDX - offset of IRQ handler
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
dp_getirqvect:
push ax ebx cx
movzx ebx,bl
mov bl,intslottbl[ebx]
mov ax,204h
int 31h
pop cx ebx ax
ret
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; DPMI set IRQ handler offset
; In:
; BL - IRQ num (0-0fh)
; EDX - offset of IRQ handler
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
dp_setirqvect:
push ax ebx cx
movzx ebx,bl
mov bl,intslottbl[ebx]
mov cx,cs
mov ax,205h
int 31h
pop cx ebx ax
ret
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
; Set the base addx for a selector
; In:
; AX - selector
; EDX - linear base addx for selector
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
dp_setselector:
if SELECTORS ne 0
push ax bx ecx
shld ecx,edx,16
mov bx,ax
mov ax,7
int 31h
pop ecx bx ax
endif
ret
code32 ends
;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
; End of program (must be at end of program or you will suffer)
;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
codeend segment para stack use32 'stack'
db STAKSIZE*16 dup(?)
codeend ends
end start16